package com.hulytu.invasion;

import com.hulytu.invasion.plugin.EnhancePlugin;

import org.jetbrains.annotations.NotNull;

import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 绑定对象缓存
 *
 * @since 1.0.2
 */
class EnhanceStoreV2 {

    private static final EnhanceStoreV2 STORE = new EnhanceStoreV2();

    static EnhanceStoreV2 instance() {
        return STORE;
    }

    private final Map<String, Set<Store<?>>> stores = new ConcurrentHashMap<>();

    private EnhanceStoreV2() {
    }

    @SuppressWarnings("unchecked")
    <T> EnhancePlugin<T> findPlugin(String plugin, @NotNull T host, boolean create) {
        EnhancePlugin<T> cache = Embrace.findPlugin(plugin);
        if (cache == null) return null;

        Object obj = cache.getHost();
        if (obj != null && obj.equals(host)) return cache;

        Set<Store<?>> stores = this.stores.get(plugin);
        Set<Store<?>> set;
        if (stores == null) {
            set = new CopyOnWriteArraySet<>();
            this.stores.put(plugin, set);
        } else {
            set = stores;
            for (Store<?> store : set) {
                Object object = store.host;
                if (host.equals(object)) return (EnhancePlugin<T>) store.plugin;
            }
        }

        if (!create) return null;

        // 代表没有找到
        EnhancePlugin<T> newInstance = createNewPlugin(cache);

        if (newInstance == null) return null;

        Store<T> store = new Store<>();
        store.host = host;
        store.plugin = newInstance;

        set.add(store);

        return newInstance;
    }

    @SuppressWarnings("unchecked")
    private <T> EnhancePlugin<T> createNewPlugin(@NotNull EnhancePlugin<T> cache) {
        Class<T> clazz = (Class<T>) cache.getClass();
        try {
            return (EnhancePlugin<T>) clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    void releasePlugin(String plugin, @NotNull Object host) {
        EnhancePlugin<?> cache = Embrace.findPlugin(plugin);
        if (cache == null) return;

        Object obj = cache.getHost();
        if (obj != null && obj.equals(host)) return;

        Set<Store<?>> set = stores.get(plugin);
        if (set == null) return;

        Iterator<Store<?>> itr = set.iterator();
        while (itr.hasNext()) {
            Store<?> store = itr.next();
            if (Objects.equals(host, store.host)) {
                itr.remove();
            }
        }
    }

    static class Store<T> {
        private T host;
        private EnhancePlugin<T> plugin;

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Store<?> store = (Store<?>) o;
            return Objects.equals(host, store.host) && Objects.equals(plugin, store.plugin);
        }

        @Override
        public int hashCode() {
            return Objects.hash(host, plugin);
        }
    }

}
